
package com.x52im.rbchat.logic.search.impl;

import android.os.Handler;
import android.os.HandlerThread;
import android.util.Log;

import com.eva.epc.common.util.CommonUtils;
import com.x52im.rbchat.logic.search.content.SearchableContent;
import com.x52im.rbchat.logic.search.model.SearchCompleteData;

import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;

import java.util.List;

/**
 * 搜索功能对应的ViewModel对象实现类。
 * 利用LiveData+ViewModel实现数据的查找逻辑跟UI界面解偶。
 *
 * @author JackJiang
 * @since 8.2
 */
public class DataSourceViewModel extends ViewModel {

    private final static String TAG = DataSourceViewModel.class.getSimpleName();

    /** 搜索结果LiveData对象(UI层可对此对象添加观察者从而接收数据查询结果) */
    private MutableLiveData<SearchCompleteData> resultLiveData = null;
    /** 当前搜索的关键字 */
    private String keyword = null;

    /** 提交查找任何的后台Handler对象 */
    private Handler backgroundHandler = null;
    /** 主线程Handler（用于接收后台线程执行后的结果）*/
    private Handler mainHandler = new Handler();
    /** 后台线程对象（HandlerThread可保证后台任何的执行都是顺序进行）*/
    private HandlerThread serialThread = null;

    public DataSourceViewModel() {
        // 初始化LiveData对象
        resultLiveData = new MutableLiveData<>();
        // 初始化后台线程和Handler
        if (backgroundHandler == null) {
            // 可序列化执行后台任何的线程
            serialThread = new HandlerThread("search");
            // HandlerThread必须start后，后绪才可以向它post后台任务
            serialThread.start();
            // 后台任务Handler对象
            backgroundHandler = new Handler(serialThread.getLooper());
        }
    }

    /**
     * 本ViewModel类被回收时将要做的处理。
     */
    @Override
    protected void onCleared() {
        super.onCleared();

        Log.i(TAG, "@@@@【搜索功能-DataSourceViewModel】onCleared被调用了！");

        // 确保后台线程安全退出
        if(serialThread != null){
            serialThread.quit();
        }
    }

    /**
     * 实施数据搜索。
     *
     * @param k                  要搜索的关键字
     * @param searchableContents 本地次搜索数据对应的搜索范围描述对象集合
     */
    public void doSearch(String k, List<SearchableContent> searchableContents) {
        if (CommonUtils.isStringEmpty(k)) {
            Log.w(TAG, "无效的搜索关键字，k=null !");
            return;
        }

        if (this.keyword != null && this.keyword.equals(k)) {
            Log.w(TAG, "重复的关键字搜索，本次搜索任务被忽略（k=" + k + "） !");
            return;
        }

        // 把本次关键字保存
        this.keyword = k;
        // 开始提交后台搜索任务
        this.backgroundHandler.post(() -> {

            // 是否匹配到关键字
            boolean matched = false;
            // 在可搜索内容对象集合中遍历这个搜索关键字
            for (SearchableContent c : searchableContents) {
                // 返回的搜索结果
                List r = c.doSearch(k, c.isShowAllResult());
                // 如果结果不为空
                if (k.equals(keyword) && r != null && r.size() > 0) {
                    matched = true;
                    // 将搜索结果通知主线程，以便ui界面刷新显示
                    mainHandler.post(() -> resultLiveData.setValue(new SearchCompleteData(c, r)));
                }
            }

            // 如果没有匹配到结果也要通知ui界面，以便ui界面清空显示
            if (k.equals(keyword) && !matched) {
                mainHandler.post(() -> resultLiveData.setValue(null));
            }

            // 本次搜索结束，清空暂存的搜索关键字
            this.keyword = null;
        });
    }

    /**
     * 返回搜索结果LiveData对象。
     *
     * @return 搜索结果LiveData对象引用
     */
    public MutableLiveData<SearchCompleteData> getResultLiveData() {
        return resultLiveData;
    }
}
